﻿#include "klb_type.h"
#include "klbmem/klb_mem.h"
#include "klbmem/klb_buf.h"
#include "klbutil/klb_rect.h"
#include "klua/klua.h"
#include "SDL.h"
#include "libge2d_extension.h"
#include "core/klbge2d.h"
#include "core/world.h"
#include <assert.h>


#define KLUA_LIBGE2D_HANDLE     "KLUA_LIBGE2D_HANDLE*"

// 
typedef struct klua_libge2d_t_
{
    klua_env_t*             p_env;          ///< lua环境
    lua_State*              L;              ///< L

    libge2d_extension_t*    p_ge2d_ex;      ///< ge2d 扩展
    klbge2d_t*              p_ge2d;         ///< ge2d
    world_t*                p_world;        ///< game 世界
}klua_libge2d_t;


///////////////////////////////////////

static klua_libge2d_t* new_klua_libge2d(lua_State* L)
{
    klua_libge2d_t* p_libge2d = (klua_libge2d_t*)lua_newuserdata(L, sizeof(klua_libge2d_t));
    KLB_MEMSET(p_libge2d, 0, sizeof(klua_libge2d_t));
    luaL_setmetatable(L, KLUA_LIBGE2D_HANDLE);

    // 初始化
    p_libge2d->L = L;
    p_libge2d->p_env = klua_env_get_by_L(L);

    p_libge2d->p_ge2d_ex = kluaex_get_libge2d(p_libge2d->p_env);
    p_libge2d->p_ge2d = libge2d_extension_get(p_libge2d->p_ge2d_ex);
    p_libge2d->p_world = klbge2d_get_world(p_libge2d->p_ge2d);

    return p_libge2d;
}

static klua_libge2d_t* to_klua_libge2d(lua_State* L, int index)
{
    klua_libge2d_t* p_libge2d = (klua_libge2d_t*)luaL_checkudata(L, index, KLUA_LIBGE2D_HANDLE);
    luaL_argcheck(L, NULL != p_libge2d, index, "'libge2d' expected");
    return p_libge2d;
}

static int klua_libge2d_tostring(lua_State* L)
{
    klua_libge2d_t* p_libge2d = to_klua_libge2d(L, 1);

    lua_pushfstring(L, "libge2d:%p", p_libge2d);
    return 1;
}

///////////////////////////////////////

static int klua_libge2d_close(lua_State* L)
{
    klua_libge2d_t* p_libge2d = to_klua_libge2d(L, 1);

    return 0;
}

static int klua_libge2d_append(lua_State* L)
{
    klua_libge2d_t* p_libge2d = to_klua_libge2d(L, 1);
    const char* p_type = luaL_checkstring(L, 2);
    const char* p_scene = luaL_checkstring(L, 3);
    const char* p_path = NULL;

    if (LUA_TSTRING == lua_type(L, 4))
    {
        p_path = luaL_checkstring(L, 4);
    }

    int ret = world_append(p_libge2d->p_world, p_type, p_scene, p_path);

    lua_pushinteger(L, ret);
    return 1;
}

static int klua_libge2d_remove(lua_State* L)
{
    klua_libge2d_t* p_libge2d = to_klua_libge2d(L, 1);
    const char* p_scene = luaL_checkstring(L, 2);
    const char* p_path = luaL_checkstring(L, 3);

    int ret = world_remove(p_libge2d->p_world, p_scene, p_path);

    lua_pushinteger(L, ret);
    return 1;
}

//////////////////////////////////////////////////////////////////////////

static void klua_libge2d_createmeta(lua_State* L)
{
    static luaL_Reg meth[] = {
        // 对game世界操作
        { "append",             klua_libge2d_append },
        { "remove",             klua_libge2d_remove },

        { NULL,                 NULL }
    };

    static const luaL_Reg metameth[] = {
        { "__index",         NULL },  /* place holder */
        { "__gc",            klua_libge2d_close },
        { "__close",         klua_libge2d_close },
        { "__tostring",      klua_libge2d_tostring },
        { NULL,              NULL }
    };

    luaL_newmetatable(L, KLUA_LIBGE2D_HANDLE); /* metatable for KLUA_LIBGE2D_HANDLE handles */
    luaL_setfuncs(L, metameth, 0);          /* add metamethods to new metatable */
    luaL_newlibtable(L, meth);              /* create method table */
    luaL_setfuncs(L, meth, 0);              /* add file methods to method table */
    lua_setfield(L, -2, "__index");         /* metatable.__index = method table */
    lua_pop(L, 1);                          /* pop metatable */
}


//////////////////////////////////////////////////////////////////////////


// 获取可执行文件的路径
static int libge2d_SDL_GetBasePath(lua_State* L)
{
    char* p_base_path = SDL_GetBasePath();

    lua_pushstring(L, p_base_path);

    KLB_FREE_BY(p_base_path, SDL_free);
    return 1;
}

// 获取系统分配的应用配置路径
static int libge2d_SDL_GetPrefPath(lua_State* L)
{
    const char* p_org = luaL_checkstring(L, 1);
    const char* p_app = luaL_checkstring(L, 2);

    char* p_pref_path = SDL_GetPrefPath(p_org, p_app);

    lua_pushstring(L, p_pref_path);

    KLB_FREE_BY(p_pref_path, SDL_free);
    return 1;
}

static int libge2d_init(lua_State* L)
{
    int w = luaL_checkinteger(L, 1);
    int h = luaL_checkinteger(L, 2);
    const char* p_title = luaL_checkstring(L, 3);

    libge2d_extension_t* p_ex = kluaex_get_libge2d_by_L(L);

    libge2d_extension_init(p_ex, w, h, p_title);

    // 
    new_klua_libge2d(L);
    return 1;
}

static int libge2d_quit(lua_State* L)
{
    libge2d_extension_t* p_ex = kluaex_get_libge2d_by_L(L);
    
    libge2d_extension_quit(p_ex);

    return 0;
}

static int libge2d_new(lua_State* L)
{
    // 
    new_klua_libge2d(L);
    return 1;
}

KLB_API int luaopen_libge2d(lua_State* L)
{
    static luaL_Reg lib[] =
    {
        { "get_base_path",      libge2d_SDL_GetBasePath },
        { "get_pref_path",      libge2d_SDL_GetPrefPath },

        { "init",               libge2d_init },
        { "quit",               libge2d_quit },
        { "new",                libge2d_new },

        { NULL,                 NULL }
    };

    // 创建导出库函数
    luaL_newlib(L, lib);

    // KLUA_KLPC_MODULE_HANDLE
    klua_libge2d_createmeta(L);

    return 1;
}
